#ifndef RUN_FUNCTIONS_H
#define RUN_FUNCTIONS_H

#include "main.h"

#ifndef FALSE
  #define FALSE 0
#endif

#ifndef TRUE
  #define TRUE 1
#endif

/* Define the default field size 2^m and error-correction capacity t*/
#define DEFAULT_M 3
#define DEFAULT_T (((1<<DEFAULT_M)/2)-2)

// Define an argument structure to contain all input parameter values.
typedef struct {
    /* General program options */
    int help;            // Indicates that the help flag has been entered
                         // Command line switch: -h

    int verbose;         // Print out status messages as program executes
                         // Command line switch: -v

    int test;            // Run program tests and print test output to stdout
                         // Command line switch: -T

    /* Galois Field and Code Properties */
    int m;               // Galois Field order - work in GF(2^m)
                         // Command line switch: -m <value>

    int t;               // Generate a t-error-correcting code
                         // Command line switch: -t <value>

    /* Parallelization Parameters */
    int num_DEs;         // Number of decoding elements (openMP elements)
                         // Command line switch: -D <value>

    int decoder_mode;    // Mode for the decoder (default: serial)
                         // Options are:
                         // MODE_SERIAL           No parallelization
                         // MODE_PTHREAD          Pthread parallelization
                         // MODE_OPENMP_STATIC    OpenMP with static allocation
                         // MODE_OPENMP_GUIDED    OpenMP with guided allocation
                         // MODE_OPENMP_DYNAMIC   OpenMP with dynamic allocation
                         // Command line switch: -M

    /* Data Source Properties 
       Several data sources are possible, as seen as follows: */
        
    /* 1. Input file */
    char * ifile;        // Input data file
                         // Command line switch: -i <filename>
    /* Output decoded data file */
    char * dfile;        // Output decoded data file
                         // Command line switch: -f

    /* 2. Generate data at runtime */
    char * ofile;        // Save the generated data in the file ofile instead
                         // of deleting temporary file.
                         // Command line switch: -o <filename>

    int gen_data;        // Generate new data, don't read from a file
                         // Command line switch: -g

    int no_run;          // Don't run the RS simulation, just generate data.
                         // Command line switch: -N

    int data_length;     // Length (in data symbols) of new data to be generated
                         // Command line switch: -l <length>
    
    /* Generate the data with a single error probability at each symbol, all 
       symbols iid */
    double e_prob;       // Prob. of error in each symbol in generated data
                         // Command line switch: -p <value>

    /* Generate a fixed number of errors per code word, according to a 
       given distribution */
    int e_per_word;      // Fixed number of errors per word
                         // Command line switch: -e <value>

    char *e_pmf;         // Probability distribution (pmf) of error locations
                         // Has to be parsed out into an array of doubles
                         // Number of entries has to match code word length
                         // Command line switch: -d <value>

} ArgStruct;

// Define the possible return statuses for checkArgs()
#define ARG_FAILURE 0
#define ARG_SUCCESS 1

// Define the decoder modes
// Note: these are shared in the Python code
#define MODE_SERIAL         0
#define MODE_PTHREAD        1
#define MODE_OPENMP_STATIC  2
#define MODE_OPENMP_GUIDED  3
#define MODE_OPENMP_DYNAMIC 4

// Define the program help string
#define HELPSTRING "This is the help string\n"

/* Parse command line arguments using the optlist library and populate an 
   ArgStruct.  Do not perform any arg checking; this is to be done in 
   the function checkArgs() */
ArgStruct * parseArgs(int argc, char * argv[]);

/* Check all values populated into the input ArgStruct and confirm that they
   are legal values for their respective variables.  Report to stderr and exit 
   if any invalid values or other errors are encountered. */
int checkArgs(ArgStruct * args);

/* Parse values out of a character array to populate an array for e_pmf. Need 
   to check that there are the proper number of entries, and that the sum of 
   the entries is 1. */
double * parse_pmf(char *e_pmf, int m, int t);

#endif

